package core;

import java.util.ArrayList;

import org.w3c.dom.css.Counter;

import parsing.Parser;

import functions.Function;

public class BisectionMethod extends Method {

	private int counter = 0;
	private double initialX;
	private double finalX;
	private ArrayList<Point> res;

	public BisectionMethod(int numOfIteration, double precision, double a,
			double b) {
		super(numOfIteration, precision);
		initialX = a;
		finalX = b;
		res = new ArrayList<Point>();
	}

	/**
	 * This recursive method changes the interval till f(x)=0.
	 * 
	 * @param left
	 * @param right
	 * @param fun
	 * @return
	 */
	public ArrayList<Point> recursion(double left, double right, Function fun) {
		double middle = (left + right) / 2;
		Point a = new Point(left, fun.eval(left));
		Point b = new Point(right, fun.eval(right));
		res.add(a);
		res.add(b);
		if (counter < numOfIteration) {
			if (fun.eval(middle) > (-1 * precision)
					&& fun.eval(middle) < (precision)) {
				Point p = new Point(middle, fun.eval(middle));
				res.add(p);
				return res;
			} else if (fun.eval(middle) * fun.eval(left) < 0) {
				Point p1 = new Point(left, fun.eval(left));
				Point p2 = new Point(middle, fun.eval(middle));
				res.add(p1);
				res.add(p2);
				recursion(left, middle, fun);
			} else if (fun.eval(middle) * fun.eval(right) < 0) {
				Point p2 = new Point(middle, fun.eval(middle));
				Point p1 = new Point(right, fun.eval(right));
				res.add(p1);
				res.add(p2);
				recursion(middle, right, fun);
			}
			counter++;
		}
		return res;
	}

	@Override
	public ArrayList<Point> run(Function f) throws Exception {
//		if (f.eval(finalX) * f.eval(initialX) >= 0)
//			throw new Exception("Can't evaluate !");
		return recursion(initialX, finalX, f);
	}

	@Override
	public double getErrorBound() {
		return ((initialX+finalX)/Math.pow(2, counter+1));
	}

	/**
	 * There are some test cases in the main method .
	 * 633663
	 * @param args
	 * @throws Exception
	 */
	public static void main(String[] args) throws Exception {
		Parser p = new Parser();
		Function f = p.parse("x^2 - 3*x^1 +2");
		BisectionMethod bisec = new BisectionMethod(10, 0.00000000001, 3, 1.5);
		bisec.run(f);
		System.out
				.println("The value of x such taht f(x) ~ 0 : \n==================================");
		System.out
				.println("x= : " + bisec.res.get(bisec.res.size() - 1).getX());
		System.out.println("the # iterations is :" + bisec.counter);
	}

}